#pragma once

#include <thread>
#include <mutex>
#include <chrono>
#include <unordered_map>
#include <atomic>
#include <functional>
#include <future>

#include "taskQueue.hpp"

namespace lakes {
    
    enum THREAD_STATU {
        WAITTING = 1,
        WORKING,
        DEAD
    };

    using WorkTaskType = std::function<void()>;

    class ThreadPool final {
    public:
        /**
         * 构造函数: 
         * min_thread: 最小线程数
         * max_thread: 最大线程数
         * isStart: 是否开始 默认 true
        */
        ThreadPool(int min_thread, int max_thread, bool isStart = true);
        
        /**
         *  析构函数, 内部默认调用finish().
        */
        ~ThreadPool();

        /**
         * 添加任务.
        */
        template<typename Func, typename ...Args>
        auto commit(Func&& func, Args&& ...args) -> std::future<decltype(func(args...))> {

            using RetType = decltype(func(args...));

            std::shared_ptr<std::packaged_task<RetType()>> task = std::make_shared<std::packaged_task<RetType()>>(
			    std::bind(std::forward<Func>(func), std::forward<Args>(args)...)
			);
		    
            if (isRun()) {
                m_taskQueue.putTask([task]() {                 
                    (*task)();
                });
            }
            
            return task->get_future();
        }  
        
        /**
         * 启动线程池.
        */
        void start();

        /**
         * 停止线程池, 析构函数默认会调用.
        */
        void finish();

        /**
         * 获取最小线程数.
        */
        int getMinThreadNumber();

        /**
         * 获取最大线程数.
        */
        int getMaxThreadNumber();

        /**
         * 获取任务队列数.
        */
        int getTaskQueueNumber(); 

        /**
         * 获取正在忙活的线程数.
        */
        int getBusyThreadNumber();

        /**
         * 获取存活的线程数.
        */
        int getLiveThreadNumber();

        /**
         * 设置钩子函数, 用于监视线程池状况.
         * ms 间隔时间 毫秒.
         * hookCallback 钩子回调.
        */
        void setHook(int ms, std::function<void(ThreadPool*)> hookCallback);

        /**
         * 是否启动.
        */
        bool isRun();

    private:
        bool m_isRunning;
        int m_minThreadNum;
        int m_maxThreadNum;
        
        std::atomic_uint m_busyThreadNum;     
        std::atomic_uint m_willKillThreadNum;
        std::atomic_uint m_liveThreadNum;

        TaskQueue<WorkTaskType> m_taskQueue;

        std::mutex m_PoolMutex;
            
        std::unordered_map<std::thread::id, std::thread*> m_threadWorkMap;
        std::thread* m_threadManager = nullptr;
        std::thread* m_threadHook = nullptr;
        
        static constexpr int ONCE_KILL_THREADA  = 2;
        static constexpr int ONCE_CREATE_THREADA = 2;
        static constexpr int MANAGER_INTERVAL_MS = 3000;

        void init(int min_thread, int max_thread);
        void addManagerThread();
        void addNewWorkThread();
        void killSelfThread(bool isCover);

    };
} // namespace lakes



